package com.jh.paymentchannel.service;

import cn.jh.common.utils.CommonConstants;
import com.alibaba.fastjson.TypeReference;
import com.jh.paymentchannel.business.BranchbankBussiness;
import com.jh.paymentchannel.business.TopupPayChannelBusiness;
import com.jh.paymentchannel.pojo.BranchNo;
import com.jh.paymentchannel.pojo.ChannelDetail;
import com.jh.paymentchannel.pojo.MiLianRegister;
import com.jh.paymentchannel.util.Util;
import com.jh.paymentchannel.util.milian.bean.*;
import com.jh.paymentchannel.util.milian.utils.HttpHelper;
import com.jh.paymentchannel.util.milian.utils.ParamsUtil;
import net.sf.json.JSONObject;
import okhttp3.MediaType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Controller
@EnableAutoConfiguration
public class MiLianPageService {
    private static final Logger log = LoggerFactory.getLogger(MiLianPageService.class);

    public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

    @Value("${milian.key}")
    private String key;

    @Value("${milian.parent}")
    private String parent;

    @Value("${payment.ipAddress}")
    private String ipAddress;

    @Autowired
    private TopupPayChannelBusiness topupPayChannelBusiness;

    @Autowired
    private BranchbankBussiness branchbankBussiness;

    @Autowired
    private Util util;

    /*进件URL*/
    @Value("${milian.RegisterUrl}")
    private String RegisterUrl;// = "http://220.160.118.218:8382/ChannelPay/merchBaseInfo/merchInterface";
    // private String RegisterUrl = "http://222.76.210.177:9006/ChannelPay/merchBaseInfo/merchInterface"; // product

    /*交易URL*/
    @Value("${milian.TransactionUrl}")
    private String TransactionUrl;// = "http://220.160.118.218:8281/MyLandQuickPay/servlet/QuickPay";

    /**
     * 米联进件 含 新增与更新
     *
     * @param orderCode order code
     * @param userId User Id
     * @param provinceOfBank  province of bank
     * @param cityOfBank city of bank
     * @param bankBranchName bank branch name
     * @return Map
     */
    private Map miLianJinJian(String orderCode, String userId, String provinceOfBank, String cityOfBank, String bankBranchName) {

        log.info("米联进件 miLianJinJian 包含新增与自动更新=====" + parent);
        Map resultMap = new HashMap();

        // --- check order
        RestTemplate restTemplate = new RestTemplate();
        URI uri = util.getServiceUrl("transactionclear", "error url request!");
        String url = uri.toString() + "/v1.0/transactionclear/payment/query/ordercode";
        MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<String, String>();
        requestEntity.add("order_code", orderCode);
        String result = restTemplate.postForObject(url, requestEntity, String.class);
        log.info("米联进件 miLianJinJian 查询订单信息RESULT================" + result);
        JSONObject jsonObject;
        JSONObject orderResultObj;
        try {
            jsonObject = JSONObject.fromObject(result);
            orderResultObj = jsonObject.getJSONObject("result");
        } catch (Exception e1) {
            log.error("查询订单信息出错");
            resultMap.put(CommonConstants.RESP_CODE, CommonConstants.FALIED);
            resultMap.put(CommonConstants.RESP_MESSAGE, "没有该订单信息");
            return resultMap;
        }

        // --- check user
        uri = util.getServiceUrl("user", "error url request!");
        url = uri.toString() + "/v1.0/user/query/id";
        requestEntity = new LinkedMultiValueMap<String, String>();
        requestEntity.add("id", userId );
        restTemplate = new RestTemplate();
        JSONObject userResultObj;
        try {
            result = restTemplate.postForObject(url, requestEntity, String.class);
            jsonObject = JSONObject.fromObject(result);
            userResultObj = jsonObject.getJSONObject("result");
        } catch (Exception e) {
            log.error("==========米联进件 miLianJinJian /v1.0/user/query/id查询用户异常===========" + e);
            resultMap.put(CommonConstants.RESP_CODE, CommonConstants.FALIED);
            resultMap.put(CommonConstants.RESP_MESSAGE, "查询用户异常");
            return resultMap;
        }

        // --- check user withdraw bank
        restTemplate = new RestTemplate();
        uri = util.getServiceUrl("user", "error url request!");
        url = uri.toString() + "/v1.0/user/bank/default/userid";
        requestEntity = new LinkedMultiValueMap<String, String>();
        requestEntity.add("user_id", userId);
        result = restTemplate.postForObject(url, requestEntity, String.class);
        log.info("米联进件 miLianJinJian 查询默认结算卡RESULT================" + result);
        JSONObject withdrawBankresultObj;
        try {
            jsonObject = JSONObject.fromObject(result);
            withdrawBankresultObj = jsonObject.getJSONObject("result");
        } catch (Exception e1) {
            resultMap.put(CommonConstants.RESP_CODE, CommonConstants.FALIED);
            resultMap.put(CommonConstants.RESP_MESSAGE, "查询默认结算卡有误");
            return resultMap;
        }
        String respcode = jsonObject.getString("resp_code");
        if (!"000000".equals(respcode)) {
            resultMap.put(CommonConstants.RESP_CODE, CommonConstants.FALIED);
            resultMap.put(CommonConstants.RESP_MESSAGE, "没有结算卡");
            return resultMap;
        }
        String bankName = withdrawBankresultObj.getString("bankName");
        if (bankName.contains("邮")) {
            bankName = "中国邮政";
        } else if (bankName.contains("浦")) {
            bankName = "浦发银行";
        }
        // 根据银行名称获取银行编码
        restTemplate = new RestTemplate();
        uri = util.getServiceUrl("user", "error url request!");
        url = uri.toString() + "/v1.0/user/bankcode/getcodebyname";
        requestEntity = new LinkedMultiValueMap<String, String>();
        requestEntity.add("name", bankName);
        result = restTemplate.postForObject(url, requestEntity, String.class);
        log.info("米联进件 miLianJinJian 获取银行编码RESULT================" + result);
        try {
            jsonObject = JSONObject.fromObject(result);
        } catch (Exception e) {
            log.error("米联进件 miLianJinJian -- 根据银行名称获取银行编码失败 bankName:" + bankName);
            resultMap.put(CommonConstants.RESP_CODE, CommonConstants.FALIED);
            resultMap.put(CommonConstants.RESP_MESSAGE, "根据银行名称获取银行编码失败");
            return resultMap;
        }
        // 银行编号
        String withdrawBankCode = jsonObject.getString("result");
        // 根据银行名称查询得到银行信息
        BranchNo findByBankName;
        try {
            findByBankName = branchbankBussiness.findByBankName(bankName);
        } catch (Exception e1) {
            log.error("米联进件 miLianJinJian -- 查询银行信息有误 bankName:" + bankName);
            resultMap.put(CommonConstants.RESP_CODE, CommonConstants.FALIED);
            resultMap.put(CommonConstants.RESP_MESSAGE, "查询银行信息有误");
            return resultMap;
        }
        // 银行总行联行号
        String withdrawBankInBankUnitNo = findByBankName.getBankNo();
        String withdrawBankBranchNo;
        try {
            log.info("米联进件 miLianJinJian -- 查询支行联行号");
            withdrawBankBranchNo = branchbankBussiness.getNumByName(bankBranchName);
        } catch (Exception e1) {
            log.error("米联进件 miLianJinJian -- 查询支行联行号有误 bankBranchName:" + bankBranchName);
            resultMap.put(CommonConstants.RESP_CODE, CommonConstants.FALIED);
            resultMap.put(CommonConstants.RESP_MESSAGE, "查询支行联行号有误");
            return resultMap;
        }

        // --- check random shops
        restTemplate = new RestTemplate();
        uri = util.getServiceUrl("user", "error url request!");
        url = uri.toString() + "/v1.0/user/query/randomshopid";
        requestEntity = new LinkedMultiValueMap<String, String>();
        String randomShopId;
        try {
            result = restTemplate.postForObject(url, requestEntity, String.class);
            jsonObject = JSONObject.fromObject(result);
            randomShopId = jsonObject.getString("result");
        } catch (Exception e1) {
            log.error(" 米联进件 miLianJinJian 随机获取的 shopId出错！！！！");
            resultMap.put(CommonConstants.RESP_CODE, CommonConstants.FALIED);
            resultMap.put(CommonConstants.RESP_MESSAGE, "进件商户失败");
            return resultMap;
        }
        log.info("随机获取的 shopId:" + randomShopId);
        restTemplate = new RestTemplate();
        uri = util.getServiceUrl("user", "error url request!");
        url = uri.toString() + "/v1.0/user/shops/query/shopid";
        requestEntity = new LinkedMultiValueMap<String, String>();
        requestEntity.add("shopid", randomShopId);
        result = restTemplate.postForObject(url, requestEntity, String.class);
        log.info("shop info by shopId RESULT================" + result);
        JSONObject shopInfoResultObj;
        try {
            jsonObject = JSONObject.fromObject(result);
            shopInfoResultObj = jsonObject.getJSONObject("result");
        } catch (Exception e1) {
            log.error(" 米联进件 miLianJinJian 查询商铺信息出错！！！！shopId:" + randomShopId);
            resultMap.put(CommonConstants.RESP_CODE, CommonConstants.FALIED);
            resultMap.put(CommonConstants.RESP_MESSAGE, "用户进件失败");
            return resultMap;
        }

        // ==== start mi_lian register
        // 通过 userId 查询用户进件信息
        MiLianRegister miLianRegister = null;
        try {
            miLianRegister = topupPayChannelBusiness.getMiLianRegister(Long.valueOf(userId));
            log.info("查询米联进件 miLianJinJian={}",miLianRegister);
        } catch (Exception e2) {
            log.info("查询米联进件 miLianJinJian 失败");
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }
        log.info("米联进件 miLianJinJian 开始检查进件相关数据 -- ");
        String orderExtraFeeStr = orderResultObj.getString("extraFee");
        String rate = orderResultObj.getString("rate");
        String userPhone = userResultObj.getString("phone");
        String withdrawBankUserName = withdrawBankresultObj.getString("userName");
        String withdrawBankCardNo = withdrawBankresultObj.getString("cardNo");
        String withdrawBankIdCard = withdrawBankresultObj.getString("idcard"); // 身份证
        String withdrawBankPhone = withdrawBankresultObj.getString("phone");
        String withdrawBankName = withdrawBankresultObj.getString("bankName");
        String shopName = shopInfoResultObj.getString("name");
        String shopAddress = shopInfoResultObj.getString("shopsaddress");

        MiLianReginsterBean miLianReginsterBean = new MiLianReginsterBean();
        miLianReginsterBean.setOrderId(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()));
        miLianReginsterBean.setParent(parent);
        miLianReginsterBean.setFutureMinAmount("0"); // 保底 目前没有用
        miLianReginsterBean.setDebitCapAmount("9999"); // 封顶 目前没有用
        BigDecimal countFeeT0 = new BigDecimal(orderExtraFeeStr).multiply(new BigDecimal("100")); // 单位转成分, 元->分
        miLianReginsterBean.setCountFeeT0(countFeeT0.stripTrailingZeros().toPlainString());
        miLianReginsterBean.setDebitRate(rate);
        miLianReginsterBean.setBankProvince(provinceOfBank);
        miLianReginsterBean.setBankCity(cityOfBank);
        miLianReginsterBean.setTelNo(userPhone);
        miLianReginsterBean.setBankAccountName(withdrawBankUserName);
        miLianReginsterBean.setBankAccountNo(withdrawBankCardNo);
        miLianReginsterBean.setLegalPersonIdcard(withdrawBankIdCard);
        miLianReginsterBean.setPhoneNo(withdrawBankPhone);
        miLianReginsterBean.setSettBankName(withdrawBankName);
        miLianReginsterBean.setBankAbbr(withdrawBankCode);
        miLianReginsterBean.setBankChannelNo(withdrawBankInBankUnitNo);
        miLianReginsterBean.setBankCode(withdrawBankInBankUnitNo);
        miLianReginsterBean.setBankSubName(withdrawBankBranchNo);

        String HandleType = "A";
        String miLianChangeType = "";
        if (miLianRegister == null) {
            log.info("米联进件 miLianJinJian 用户需要进件===newJinJian===== orderCode:" + orderCode + " withdrawBank:" + withdrawBankCardNo);
            // 新增加 进件
            miLianReginsterBean.setHandleType(HandleType);  // A 新增进件

            miLianReginsterBean.setMerchName(shopName);
            miLianReginsterBean.setMerchAbb(shopName);
            miLianReginsterBean.setMerchAddress(shopAddress);
            /*不确定*/
            miLianReginsterBean.setEmail("");
//            miLianReginsterBean.setBankCardPhoto(GetBase64StrOfImg("C:/Users/guodo/Desktop/image/bankcard.jpg").replace("+", "%2B"));
//            miLianReginsterBean.setIdCardPhoto(GetBase64StrOfImg("C:/Users/guodo/Desktop/image/face1.jpg").replace("+", "%2B"));
//            miLianReginsterBean.setIdCardBackPhoto(GetBase64StrOfImg("C:/Users/guodo/Desktop/image/face2.jpg").replace("+", "%2B"));

        }else {
            log.info("米联进件 miLianJinJian 查到用户进件信息 id:" + miLianRegister.getId());
            // check and update register data
            // 当汇率或结算卡号改变, 同步要修改米联商户信息. 米联商户修改接口
            if (!miLianRegister.getDebitRate().equals(rate) || miLianRegister.getCountFee() == null || !miLianRegister.getCountFee().equals(orderExtraFeeStr) || !withdrawBankCardNo.equalsIgnoreCase(miLianRegister.getBankCard())) {
                log.info("米联进件 miLianJinJian 修改进商信息===updateJinJian===== orderCode:" + orderCode + " mlBankNo:" +
                        miLianRegister.getBankCard() + " mlRate:" + miLianRegister.getDebitRate());

                if ((!miLianRegister.getDebitRate().equals(rate) || miLianRegister.getCountFee() == null || !miLianRegister.getCountFee().equals(orderExtraFeeStr)) &&
                        !withdrawBankCardNo.equalsIgnoreCase(miLianRegister.getBankCard())) {
                    // 要修改两次 调两次 M02:修改结算卡信息  M03:修改费率
                    log.info("米联进件 miLianJinJian 费率和结算卡都发生变化=== ordercode:" + orderCode);
                    resultMap.put(CommonConstants.RESP_CODE, CommonConstants.FALIED);
                    resultMap.put(CommonConstants.RESP_MESSAGE, "结算卡和费率都发生变化!");
                    return resultMap;
                }
                /**
                 * ! 米联不能重新进件，报错: 该服务商商户已存在。
                 * 只能修改
                 */
                miLianReginsterBean.setMerchId(miLianRegister.getMerchantNo());
                if (!withdrawBankCardNo.equalsIgnoreCase(miLianRegister.getBankCard())) {
                    miLianChangeType = "M02";
                }else{
                    miLianChangeType = "M03";
                }
                miLianReginsterBean.setChangeType(miLianChangeType); // M01:修改商户基本信息  M02:修改结算卡信息  M03:修改费率

                HandleType = "M";
                miLianReginsterBean.setHandleType(HandleType);  // A 新增进件, M 修改
                miLianReginsterBean.setMerchName(shopName);
                miLianReginsterBean.setMerchAbb(shopName);
                miLianReginsterBean.setMerchAddress(shopAddress);
                miLianReginsterBean.setEmail("");
            }
        }

        /*米联进件参数*/
        String params = ParamsUtil.getBaseMerchRegisterParams(miLianReginsterBean , key);
        log.info("米联进件 miLianJinJian 开始请求进件参数={} ordercode:" + orderCode ,params);
        String respResult = HttpHelper.doHttp(RegisterUrl, HttpHelper.POST, "UTF-8", params, "60000");

        MilianBaseResMessage<MiLianMerchan> res = com.alibaba.fastjson.JSONObject.parseObject(respResult, new TypeReference<MilianBaseResMessage<MiLianMerchan>>() {
        });

        log.info("米联进件 miLianJinJian 请求入驻接口响应内容：" + res.getRespMsg());
        if (res.getRespCode() != null && "0000".equals(res.getRespCode())) {
            log.info("米联进件 success：" + res.getRespCode());
            String merchantKey = "";
            String merchantNo = "";
            if (HandleType != null && "M".equals(HandleType)) {
                log.info(miLianChangeType+"米联进件 miLianJinJian 标记删除表数据 userId:" + userId + " bank:" + miLianRegister.getBankCard());
                Integer deleteMl = topupPayChannelBusiness.deleteMiLianRegister(Long.valueOf(userId), miLianRegister.getBankCard());
                log.info(miLianChangeType+"米联进件 miLianJinJian 标记删除表数据:" + deleteMl);
                merchantKey = miLianRegister.getMerchantKey();
                merchantNo = miLianRegister.getMerchantNo();
            }else{
                if (res.getData() != null ){
                    merchantKey = res.getData().getMerchantKey();
                    merchantNo = res.getData().getMerchantNo();
                }
            }
            log.info("米联进件成功-userId:" + userId + " merchant_no:"+merchantNo+ " merchant_key:" + merchantKey);
            log.info("米联进件 miLianJinJian 进件成功后处理开始 ordercode:" + orderCode);
            MiLianRegister mlRegister = new MiLianRegister();
            mlRegister.setUserId(Long.parseLong(userId));
            mlRegister.setBankCard(withdrawBankCardNo);
            mlRegister.setDebitRate(rate);
            mlRegister.setName(withdrawBankName);
            mlRegister.setMerchantNo(merchantNo);
            mlRegister.setMerchantKey(merchantKey);
            mlRegister.setIdNo(withdrawBankIdCard);
            mlRegister.setState("1");
            mlRegister.setCountFee(orderExtraFeeStr);

            MiLianRegister resultMLRegister = topupPayChannelBusiness.createMiLianRegister(mlRegister);
            log.info("米联进件 miLianJinJian 保存数据库成功, t_ml_register ordercode:" + orderCode + " mlDataId:" + resultMLRegister.getId());
            log.info("米联进件 miLianJinJian --------OK----------");
            resultMap.put(CommonConstants.RESP_CODE, CommonConstants.SUCCESS);
            resultMap.put(CommonConstants.RESP_MESSAGE, "进件成功");
            resultMap.put(CommonConstants.RESULT, resultMLRegister);
            return resultMap;
        }else {
            log.info("米联进件 miLianJinJian 进件失败====== ordercode:" + orderCode + " RespCode:" + res.getRespCode() + " msg:" + res.getRespMsg());
            resultMap.put(CommonConstants.RESP_CODE, CommonConstants.FALIED);
            resultMap.put(CommonConstants.RESP_MESSAGE, "进件失败: " + res.getRespMsg());
            return resultMap;
        }
    }

    /*进件接口*/
    @Transactional
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/topup/milian/register")
    public @ResponseBody Object register(HttpServletRequest request,
                          @RequestParam(value = "ordercode") String ordercode,
                          @RequestParam(value = "provinceOfBank") String provinceOfBank,
                          @RequestParam(value = "cityOfBank") String cityOfBank,
                          @RequestParam(value = "amount") String amount,
                          @RequestParam(value = "bankBranchName") String bankBranchName) throws Exception {
        log.info("开始进入米联进件接口========================");

        Map map = new HashMap();
        Map<String, String> maps = new HashMap<String, String>();
        RestTemplate restTemplate = new RestTemplate();
        URI uri = util.getServiceUrl("transactionclear", "error url request!");
        String url = uri.toString() + "/v1.0/transactionclear/payment/query/ordercode";
        MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<String, String>();
        requestEntity.add("order_code", ordercode);
        String result = restTemplate.postForObject(url, requestEntity, String.class);
        log.info("查询订单信息RESULT================" + result);
        JSONObject jsonObject;
        JSONObject orderResultObj;
        try {
            jsonObject = JSONObject.fromObject(result);
            orderResultObj = jsonObject.getJSONObject("result");
        } catch (Exception e1) {
            log.error("查询订单信息出错");
            map.put("resp_code", "failed");
            map.put("channel_type", "milian");
            map.put("resp_message", "没有该订单信息");
            return map;
        }

        String userid = orderResultObj.getString("userid");

        log.info(" --- start miLianJinJian --- #");
        try {
            Map mLRegister = miLianJinJian(ordercode, userid, provinceOfBank, cityOfBank, bankBranchName);
            if (CommonConstants.SUCCESS.equals(mLRegister.get(CommonConstants.RESP_CODE))) {
                map.put("resp_code", "success");
                map.put("channel_type", "milian");
                map.put("redirect_url",
                        ipAddress + "/v1.0/paymentchannel/topup/milian/quick_pay?ordercode=" + URLEncoder.encode(ordercode, "UTF-8"));
                log.info("米联用户进件成功==========");
                return map;
            }else {
                log.info("用户进件失败====== ordercode:" + ordercode);
                map.put("resp_code", "failed");
                map.put("channel_type", "milian");
                map.put("resp_message", mLRegister.get(CommonConstants.RESP_MESSAGE));
                return map;
            }
        } catch (Exception e2) {
            log.error("on milian/register --- miLianJinJian --- 出错 :" + e2.getMessage());
            map.put("resp_code", "failed");
            map.put("channel_type", "milian");
            map.put("resp_message", "进件失败");
            return map;
        }
    }


    // 跳转确认提现卡页面的中转接口
    @RequestMapping(method = RequestMethod.GET, value = "/v1.0/paymentchannel/topup/tomilianquickbankinfo")
    public String tomilianquickbankinfo(HttpServletRequest request, HttpServletResponse response, Model model)
            throws IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        log.info("/v1.0/paymentchannel/topup/tomilianquickbankinfo=========tomilianquickbankinfo");
        String bankName = request.getParameter("bankName");// 结算卡银行名称
        String bankNo = request.getParameter("bankNo");// 结算卡卡号
        String amount = request.getParameter("amount");
        String ordercode = request.getParameter("ordercode");
        String provinceOfBank = request.getParameter("provinceOfBank");
        String cityOfBank = request.getParameter("cityOfBank");
        String bankBranchName = request.getParameter("bankBranchName");
        String bankBranchId = request.getParameter("bankBranchId");
        String cardType = request.getParameter("cardType");// 结算卡的卡类型
        String isRegister = request.getParameter("isRegister");
        String cardtype = request.getParameter("cardtype");// 信用卡的卡类型
        String bankCard = request.getParameter("bankCard");// 充值卡卡号
        String cardName = request.getParameter("cardName");// 充值卡银行名称
        String expiredTime = request.getParameter("expiredTime");// 充值卡银行名称
        String securityCode = request.getParameter("securityCode");// 充值卡银行名称

        model.addAttribute("bankName", bankName);
        model.addAttribute("bankNo", bankNo);
        model.addAttribute("amount", amount);
        model.addAttribute("ordercode", ordercode);
        model.addAttribute("provinceOfBank", provinceOfBank);
        model.addAttribute("cityOfBank", cityOfBank);
        model.addAttribute("bankBranchName", bankBranchName);
        model.addAttribute("bankBranchId", bankBranchId);
        model.addAttribute("cardType", cardType);
        model.addAttribute("isRegister", isRegister);
        model.addAttribute("cardtype", cardtype);
        model.addAttribute("bankCard", bankCard);
        model.addAttribute("cardName", cardName);
        model.addAttribute("expiredTime", expiredTime);
        model.addAttribute("securityCode", securityCode);

        return "milianquickbankInfo";
    }

    /* 米联快捷支付 */
    @RequestMapping(method = RequestMethod.GET, value = "/v1.0/paymentchannel/topup/milian/quick_pay")
    public String mlPayment(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        String orderCode = request.getParameter("ordercode");

        if (!"".equals(orderCode) && orderCode.length() < 50) {
            log.info(" -- 米联快捷支付 /v1.0/paymentchannel/topup/milian/quick_pay  start#" + orderCode);
            orderCode = URLDecoder.decode(request.getParameter("ordercode"), "UTF-8");

            Map miLianQuickPay = miLianQuickPay(orderCode);
            String respCode = miLianQuickPay.get("resp_code").toString();
            String respMessage = miLianQuickPay.get("resp_message").toString();
            String returnHtml = miLianQuickPay.get("returnHtml").toString();

            log.info(" -- 米联快捷支付 /v1.0/paymentchannel/topup/milian/quick_pay  结果code:" + respCode + " msg:"+respMessage);
            model.addAttribute("resp_code", respCode);
            model.addAttribute("resp_message", respMessage);
            model.addAttribute("returnHtml", returnHtml);
        }

        return "milianquickpayredirect";
    }

    private Map miLianQuickPay(String ordercode) {

        log.info("开始进入消费支付接口========================");
        MiLianPayBean miLianPayBean = new MiLianPayBean();
        /*米联订单号不能超过 23 字符 !*/
        //miLianPayBean.setOrder_id(ordercode);
        miLianPayBean.setPay_type("13");
        miLianPayBean.setUser_type("02");
        miLianPayBean.setSign_type("03");
        miLianPayBean.setBus_code("5015");
        miLianPayBean.setCct("CNY");

        ChannelDetail channelDetail = topupPayChannelBusiness.getChannelDetailByTag("MILIAN");
        miLianPayBean.setBg_url(channelDetail.getNotifyURL());
        miLianPayBean.setPage_url(channelDetail.getReturnURL());

        /*不确定*/

        miLianPayBean.setGoods_desc("充值消费收款");
        miLianPayBean.setGoods_name("充值消费收款");

        Map map = new HashMap();
        Map<String, String> maps = new HashMap<String, String>();
        RestTemplate restTemplate = new RestTemplate();
        URI uri = util.getServiceUrl("transactionclear", "error url request!");
        String url = uri.toString() + "/v1.0/transactionclear/payment/query/ordercode";
        MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<String, String>();
        requestEntity.add("order_code", ordercode);
        String result = restTemplate.postForObject(url, requestEntity, String.class);
        log.info("查询订单信息结果RESULT================" + result);
        JSONObject jsonObject;
        JSONObject resultObj;
        try {
            jsonObject = JSONObject.fromObject(result);
            resultObj = jsonObject.getJSONObject("result");
        } catch (Exception e1) {
            log.error("查询订单信息出错");
            map.put("resp_code", "failed");
            map.put("channel_type", "milian");
            map.put("resp_message", "没有该订单信息");
            return map;
        }

        /*米联订单号不能超过 23 字符 !*/
        String newMiLianOrderId = ordercode.substring(0,10) + resultObj.getString("id");
        miLianPayBean.setOrder_id(newMiLianOrderId);
        log.info("米联新的订单号==============" + newMiLianOrderId);

        Double amount = Double.valueOf(resultObj.getString("amount"));
        DecimalFormat df = new DecimalFormat("#.00");
        miLianPayBean.setOrder_amt(df.format(amount));

        String userid = resultObj.getString("userid");
        // 费率
        String rate = resultObj.getString("rate");
        // 额外费率
        String extraFee = resultObj.getString("extraFee");
        // 信用卡卡号 (要支付扣款的信用卡卡号)
        String payCreditCard = resultObj.getString("bankcard");

        // 通过 userId 查询用户进件信息
        MiLianRegister miLianRegister = null;
        try {
            miLianRegister = topupPayChannelBusiness.getMiLianRegister(Long.valueOf(userid),rate);
            miLianPayBean.setUser_id(miLianRegister.getMerchantNo());
            log.info("查询米联进件信息miLianRegister={}",miLianRegister);
            log.info("查询米联进件信息miLianRegister -----" + miLianRegister.getId());
        } catch (Exception e2) {
            log.error("查询米联进件信息miLianRegister ----- fail:" + e2.getMessage());
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }

        /*查询结算卡*/
        restTemplate = new RestTemplate();
        uri = util.getServiceUrl("user", "error url request!");
        url = uri.toString() + "/v1.0/user/bank/default/cardno";
        requestEntity = new LinkedMultiValueMap<String, String>();
        requestEntity.add("cardno", miLianRegister.getBankCard());
        result = restTemplate.postForObject(url, requestEntity, String.class);

        log.info("查询结算卡信息RESULT================" + result);
        try {
            jsonObject = JSONObject.fromObject(result);
            resultObj = jsonObject.getJSONObject("result");
        } catch (Exception e1) {
            log.error("查询默认结算卡出错");
            map.put("resp_code", "failed");
            map.put("channel_type", "milian");
            map.put("resp_message", "查询默认结算卡有误");
            return map;
        }
        String respcode = jsonObject.getString("resp_code");
        if (!"000000".equals(respcode)) {

            maps.put("resp_code", "failed");
            maps.put("channel_type", "milian");
            maps.put("resp_message", "没有结算卡");
            return maps;
        }

        // 默认提现卡卡号
        String withdrawBankAccountNo = resultObj.getString("cardNo");
        // 用户名
        String withdrawBankAccountName = resultObj.getString("userName");
        // 身份证号
        String idCardNo = resultObj.getString("idcard");
        // 预留手机号
        String phoneno = resultObj.getString("phone");
        // 银行名
        String withdrawBankName = resultObj.getString("bankName");

        if (withdrawBankName.contains("邮")) {
            withdrawBankName = "中国邮政储蓄银行";
        }else if (withdrawBankName.contains("浦")) {
            withdrawBankName = "上海浦东发展银行";
        }

        miLianPayBean.setName(withdrawBankAccountName);
        miLianPayBean.setId_no(idCardNo);
        miLianPayBean.setPhone_no(phoneno);
        /*结算卡*/
        miLianPayBean.setSett_acct_no(withdrawBankAccountNo);
        miLianPayBean.setCard_inst_name(withdrawBankName);

        // 查询信用卡信息
        restTemplate = new RestTemplate();
        uri = util.getServiceUrl("user", "error url request!");
        url = uri.toString() + "/v1.0/user/bank/default/cardno";
        requestEntity = new LinkedMultiValueMap<String, String>();
        requestEntity.add("cardno", payCreditCard);
        requestEntity.add("type", "0");
        result = restTemplate.postForObject(url, requestEntity, String.class);
        log.info("查询信用卡信息RESULT================" + result);
        try {
            jsonObject = JSONObject.fromObject(result);
            resultObj = jsonObject.getJSONObject("result");
        } catch (Exception e) {
            log.error("查询银行卡信息出错");
            map.put("resp_code", "failed");
            map.put("channel_type", "jf");
            map.put("resp_message", "查询银行卡信息有误");
            return map;
        }

        // 信用卡卡号
        //String cardNo = resultObj.getString("cardNo");
        miLianPayBean.setAdd1(payCreditCard);
//        String userName = resultObj.getString("userName");
        /** 身份证号 */
//        String idcard = resultObj.getString("idcard");
//        String phone = resultObj.getString("phone");
//        String bankName = resultObj.getString("bankName");

        // 根据银行名称获取银行编码
/*        restTemplate = new RestTemplate();
        uri = util.getServiceUrl("user", "error url request!");
        url = uri.toString() + "/v1.0/user/bankcode/getcodebyname";
        requestEntity = new LinkedMultiValueMap<String, String>();
        requestEntity.add("name", bankName);
        result = restTemplate.postForObject(url, requestEntity, String.class);

        log.info("RESULT================" + result);
        try {
            jsonObject = JSONObject.fromObject(result);
        } catch (Exception e) {
            log.error("根据银行名称获取银行编码失败");
            maps.put("resp_code", "failed");
            maps.put("resp_message", "根据银行名称获取银行编码失败");
            return maps;
        }

        // 银行编号
        String code = jsonObject.getString("result");*/

        /*米联支付参数*/
        String params = ParamsUtil.getQuickPayJNParams(miLianPayBean ,miLianRegister);
        log.info("米联交易参数信息params={} ordercode:" + ordercode + " newOderId:" + newMiLianOrderId,params);

        // 发送请求
        String respResult = HttpHelper.doHttp(TransactionUrl, HttpHelper.POST, "UTF-8", params, "60000");
//        BaseResMessage<MiLianResponseMsg> res  = com.alibaba.fastjson.JSONObject.parseObject(respResult, new TypeReference<BaseResMessage<MiLianResponseMsg>>() {
//        });
        log.info("调用米联交易返回respResult={} ordercode:" + ordercode + " newOderId:" + newMiLianOrderId,respResult);
        map.put("resp_code", "000000");
        map.put("resp_message", "success");
        map.put("returnHtml", respResult);
        return map;
    }


    /*支付接口*/
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/topup/milian/consume")
    public @ResponseBody Object consume(HttpServletRequest request, @RequestParam(value = "ordercode") String ordercode) throws Exception {

        log.info("------- 米联发起支付 /v1.0/paymentchannel/topup/milian/consume ----- ordercode:"+ordercode);

        Map quickPayResult = new HashMap();
        try {
            quickPayResult = miLianQuickPay(ordercode);
        } catch (Exception e) {
            log.info("------- 米联支付交易失败. /v1.0/paymentchannel/topup/milian/consume ----- ordercode:"+ordercode);
            quickPayResult.put("resp_code", CommonConstants.FALIED);
            quickPayResult.put("resp_message", "交易失败.");
        }

        return quickPayResult;
    }

    /*米联返回商户接收支付结果通知的页面地址*/
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/topup/milian/return_call")
    public String miLianReturnCallback(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {

        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        String responseDesc = URLDecoder.decode(request.getParameter("RESP_DESC"), "UTF-8");
        log.info("米联前台页面通知=====结果, code:" + request.getParameter("RESP_CODE") +
                " desc:" + responseDesc +
                " order_id:" + request.getParameter("ORDER_ID") +
                " order_amt:" + request.getParameter("ORDER_AMT") +
                " user_id:" + request.getParameter("USER_ID") +
                " bus_code:" + request.getParameter("BUS_CODE") +
                " user_type:" + request.getParameter("USER_TYPE")
        );
//        Map map = new HashMap();
//        if ("0000".equalsIgnoreCase(request.getParameter("RESP_CODE"))) {
//            map.put("resp_code", "success");
//            map.put("channel_type", "milian");
//            map.put("redirect_url", ipAddress + "/v1.0/paymentchannel/topup/sdjpaysuccess");
//            return map;
//        } else {
//            map.put("resp_code", "failed");
//            map.put("channel_type", "milian");
//            map.put("redirect_url", ipAddress + "/v1.0/paymentchannel/topup/sdjpayerror");
//            return map;
//        }

        model.addAttribute("resp_desc", responseDesc);
        if ("0000".equalsIgnoreCase(request.getParameter("RESP_CODE"))) {
            model.addAttribute("pay_result", "success");
        }else{
            model.addAttribute("pay_result", "error");
        }

        return "milianquickbankReturnPage";
    }

    /*米联返回商户接收支付结果异步通知的后台地址*/
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/topup/milian/pay_notify_call")
    public void paynotifyCall(HttpServletRequest request, HttpServletResponse response) throws Exception {

        log.info("米联异步通知 pay_notify_call --- start#");
        if ("0000".equalsIgnoreCase(request.getParameter("RESP_CODE"))) {

            // 1、检查Amount和商户系统的订单金额是否一致
            // 2、订单支付成功的业务逻辑处理请在本处增加（订单通知可能存在多次通知的情况，需要做多次通知的兼容处理）；
            // 3、返回响应内容

            /*米联订单号不能超过 23 字符 !*/
            // String newMiLianOrderId = ordercode.substring(0,10) + resultObj.getString("id");
            // 判断 payment_order: id 和 oder_code的前十位是否一致

            String miLianOrderId = request.getParameter("ORDER_ID");
            if ("".equals(miLianOrderId) || miLianOrderId.length() < 11) {
                return;
            }
            String paymentOrderId = miLianOrderId.substring(10);
            String orderCode10 = miLianOrderId.substring(0,10);

            Map map = new HashMap();
            Map<String, String> maps = new HashMap<String, String>();
            RestTemplate restTemplate = new RestTemplate();
            URI uri = util.getServiceUrl("transactionclear", "error url request!");
            String url = uri.toString() + "/v1.0/transactionclear/payment/query/orderidandcode";
            MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<String, String>();
            requestEntity.add("orderId", paymentOrderId);
            requestEntity.add("orderCode", orderCode10);
            String result = restTemplate.postForObject(url, requestEntity, String.class);
            log.info("米联异步通知 pay_notify_call --" + miLianOrderId);
            log.info("米联异步通知 pay_notify_call -- 查询订单信息结果RESULT================" + result);
            JSONObject jsonObject;
            JSONObject orderResultObj;
            try {
                jsonObject = JSONObject.fromObject(result);
                orderResultObj = jsonObject.getJSONObject("result");
            } catch (Exception e1) {
                log.error("米联异步通知 pay_notify_call -- 查询订单信息出错====" + e1.getMessage());
                return;
            }

            DecimalFormat df = new DecimalFormat("#.00");

            String orderCode = orderResultObj.getString("ordercode");
            String orderAmount = orderResultObj.getString("amount");
            Double orderAmountDouble = Double.valueOf(orderAmount);

            String userId = orderResultObj.getString("userid");
            /*异步回调返回的金额*/
            String orderAmt = request.getParameter("ORDER_AMT");
            Double orderAmtDouble = Double.valueOf(orderAmt);
            /*异步回调返回的商户号*/
            String merchantNo = request.getParameter("USER_ID");

            MiLianRegister miLianRegister = topupPayChannelBusiness.getMiLianRegister(Long.valueOf(userId));

            if (!df.format(orderAmtDouble).equals(df.format(orderAmountDouble))) {
                log.error("米联异步通知 pay_notify_call -- 订单金额不一致==== orderAmt:"+orderAmt + " orderAmount:" + orderAmount);
                return;
            }
            if (!miLianRegister.getMerchantNo().equalsIgnoreCase(merchantNo)) {
                log.error("米联异步通知 pay_notify_call -- 商户号不一致==== 米联回调返回的商户号merchantNo:"+merchantNo + " 米联进件交易的商户号merchantNo:" + miLianRegister.getMerchantNo());
                return;
            }
            synchronized (this) {
                log.info("米联异步通知 -- 开始更新订单状态 -- orderCode:" + orderCode);
                // **更新订单状态*//*
                // **调用下单，需要得到用户的订单信息*//*
                restTemplate = new RestTemplate();
                uri = util.getServiceUrl("transactionclear", "error url request!");
                url = uri.toString() + "/v1.0/transactionclear/payment/update";

                MultiValueMap<String, String> requestEntityU = new LinkedMultiValueMap<String, String>();
                requestEntityU.add("status", "1");
                requestEntityU.add("order_code", orderCode);
                requestEntityU.add("third_code", miLianOrderId);
                result = restTemplate.postForObject(url, requestEntityU, String.class);

                try {
                    jsonObject = JSONObject.fromObject(result);
                    String resp_code = jsonObject.getString(CommonConstants.RESP_CODE);
                    if(resp_code.equals(CommonConstants.SUCCESS)){
                        log.info("米联异步通知 -- 订单状态修改成功====" + result);
                    }else{
                        log.info("米联异步回调成功 -- 订单状态修改失败====" + result);
                    }
                } catch (Exception e1) {
                    log.error("米联异步通知 pay_notify_call -- 查询订单信息出错====" + e1.getMessage());
                    return;
                }

                // **判断是否有外放的通道的处理， 如果有那么继续回调外放哦*//*
                /*
                 * uri = util.getServiceUrl("transactionclear", "error url request!"); url =
                 * uri.toString() + "/v1.0/transactionclear/payment/query/ordercode";
                 *
                 * requestEntity = new LinkedMultiValueMap<String, String>();
                 * requestEntity.add("order_code", orderId); result =
                 * restTemplate.postForObject(url, requestEntity, String.class);
                 *
                 * JSONObject jsonObject = JSONObject.fromObject(result); JSONObject resultObj =
                 * jsonObject.getJSONObject("result"); String outMerOrdercode =
                 * resultObj.getString("outMerOrdercode"); String orderdesc =
                 * resultObj.getString("desc"); String phone = resultObj.getString("phone");
                 * String tranamount = resultObj.getString("amount"); String channelTag =
                 * resultObj.getString("channelTag"); String notifyURL =
                 * resultObj.getString("outNotifyUrl"); if (outMerOrdercode != null &&
                 * !outMerOrdercode.equalsIgnoreCase("")) { uri = util.getServiceUrl("channel",
                 * "error url request!"); url = uri.toString() +
                 * "/v1.0/channel/callback/yilian/notify_call"; requestEntity = new
                 * LinkedMultiValueMap<String, String>(); requestEntity.add("merchant_no",
                 * phone); requestEntity.add("amount", tranamount);
                 * requestEntity.add("channel_tag", channelTag); requestEntity.add("order_desc",
                 * URLEncoder.encode(orderdesc, "UTF-8")); requestEntity.add("order_code",
                 * outMerOrdercode); requestEntity.add("sys_order", orderId);
                 * requestEntity.add("notify_url", URLEncoder.encode(notifyURL, "UTF-8"));
                 * result = restTemplate.postForObject(url, requestEntity, String.class); }
                 */

                log.info("米联异步通知 -- success - 订单已支付! orderCode:" + orderCode);
                response.getWriter().write("SUCCESS");
            }

        }else{
            // 1、订单支付失败的业务逻辑处理请在本处增加（订单通知可能存在多次通知的情况，需要做多次通知的兼容处理，避免成功后又修改为失败）；
            // 2、返回响应内容

            log.info("米联异步通知 订单支付失败!");
        }

        log.info("米联异步通知 pay_notify_call -- END#");
    }

    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/topup/milian/updatecard")
    public @ResponseBody Object updatecard(HttpServletRequest request,
                                             @RequestParam(value = "ordercode") String ordercode, @RequestParam(value = "smsCode") String smsCode,
                                             @RequestParam(value = "expiredTime", required = false) String expiredTime,
                                             @RequestParam(value = "securityCode", required = false) String securityCode) throws Exception {



        return null;
    }

}
